﻿using Demo.Net.IdentityServer.IdentityServer;
using Demo.Net.IdentityServer.Model;
using IdentityModel.Client;
using IdentityServer4;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;

namespace Demo.Net.IdentityServer.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize(AuthenticationSchemes = IdentityServerConstants.LocalApi.AuthenticationScheme)]
    public class AuthController : ControllerBase
    {

        private readonly IHttpClientFactory _httpClientFactory;

        public AuthController(IServiceProvider serviceProvider)
        {

            _httpClientFactory = serviceProvider.GetRequiredService<IHttpClientFactory>();
        }


        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody]LoginModel model)
        {
            await Task.Yield();

            using var passport = _httpClientFactory.CreateClient("DemoNet_Idp");

            var disco = await passport.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { Policy = new DiscoveryPolicy { RequireHttps = false } });

            if (disco.IsError)
            {
                return Ok(disco.Error);
            }
            //验证账号密码后
            var tokenResponse = await passport.RequestTokenAsync(new TokenExchangeTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "demo.net.identity",
                ClientSecret = "!@#$%.demo.net.identity.709394.cert",
                GrantType = GrantTypeConst.ApLoginGrant,
                Parameters =
                {
                    { "user_name", model.UserName },
                    { "user_pwd", model.Password }
                },
                Scope = "openid profile offline_access demo.net.identity.api.all"
            });

            if (tokenResponse.IsError)
            {
                return Ok(tokenResponse.ErrorDescription ?? tokenResponse.Error);
            }
            return Ok( new
            {
                access_token = tokenResponse.AccessToken,
                refresh_token = tokenResponse.RefreshToken
            });
        }

        /// <summary>
        /// 刷新令牌
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> RefreshToken( string refreshToken)
        {
            await Task.Yield();

            using var passport = _httpClientFactory.CreateClient("DemoNet_Idp");

            var disco = await passport.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { Policy = new DiscoveryPolicy { RequireHttps = false } });

            if (disco.IsError)
            {
                return Ok(disco.Error);
            }
            var tokenResponse = await passport.RequestRefreshTokenAsync(new RefreshTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "demo.net.identity",
                ClientSecret = "!@#$%.demo.net.identity.709394.cert",
                RefreshToken = refreshToken,
                Scope = "openid profile offline_access demo.net.identity.api.all"
            });

            if (tokenResponse.IsError)
            {
                return Ok(tokenResponse.ErrorDescription ?? tokenResponse.Error);
            }
            return Ok(new
            {
                access_token = tokenResponse.AccessToken,
                refresh_token = tokenResponse.RefreshToken
            });
        }

        /// <summary>
        /// 销毁令牌
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> RevokeToken(string accessToken)
        {
            using var passport = _httpClientFactory.CreateClient("DemoNet_Idp");
            var disco = await passport.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { Policy = new DiscoveryPolicy { RequireHttps = false } });

            if (disco.IsError)
            {
                return Ok(disco.Error);
            }
            var tokenResponse = await passport.RevokeTokenAsync(new TokenRevocationRequest
            {
                Address = disco.RevocationEndpoint,
                ClientId = "demo.net.identity",
                ClientSecret = "!@#$%.demo.net.identity.709394.cert",
                Token = accessToken,
                TokenTypeHint = "access_token"
            });

            if (tokenResponse.IsError)
            {
                return Ok(tokenResponse.Error);
            }

            return Ok("注销成功");
        }




        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> WxLogin()
        {
            await Task.Yield();

            using var passport = _httpClientFactory.CreateClient("DemoNet_Idp");

            var disco = await passport.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { Policy = new DiscoveryPolicy { RequireHttps = false } });

            if (disco.IsError)
            {
                return Ok(disco.Error);
            }
            var tokenResponse = await passport.RequestTokenAsync(new TokenExchangeTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "demo.net.identity.wx",
                ClientSecret = "!@#$%.demo.net.wx.cert",
                GrantType = GrantTypeConst.WxLoginGrant,

                Scope = "openid profile offline_access demo.net.identity.api.all"
            });

            if (tokenResponse.IsError)
            {
                return Ok(tokenResponse.ErrorDescription ?? tokenResponse.Error);
            }
            return Ok(new
            {
                access_token = tokenResponse.AccessToken,
                refresh_token = tokenResponse.RefreshToken
            });
        }

    }
}
